const LOCAL_STORAGE_SESSION_KEY = 'matrix-session';

var initSync = false;
var highlightedRoom = 0;
var rooms = [];
var highlightedMsg;
var page = 'login';
var currentRoom;
var highlightedLoginInput = 0;
var scrollMsg;
var editingEvent;
var replyingToEvent;
var previousConv;

const messageBuilder = (event) => {
  const content = event.getContent();
  const sender = event.getSender();
  const date = event.getDate();
  const dateString = date.toLocaleString();
  const relation = event.getRelation();
  const floatDirection = sender === window.mClient.getUserId() ?
        'align-self:flex-end;margin-right:10px;background-color:#4dc860' :
        'align-self:flex-start;margin-left:10px;background-color:white';
  const dateDirection = sender === window.mClient.getUserId() ?
        'text-align:right;margin-right:10px;' :
        'text-align:left;margin-left:10px;';
  const reactDirection = sender === window.mClient.getUserId() ?
        'justify-content:flex-end;margin-right:10px;' :
        'justify-content:flex-start;margin-left:10px;';
  const body = content.body ? content.body.trim() : '';
  window.mClient.sendReadReceipt(event, "m.read");
  if(content.msgtype === 'm.image') {
    console.log(event);
    const imageUrl = window.mClient.mxcUrlToHttp(content.url, 50, 50, 'scale', true);
    return `
<div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
<div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}">
<img id="image-${event.getId()}" src="${imageUrl}" width=50 height=50>
</img>
</div>
<p id="datetime-${event.getId()}" style="font-size:10px;color:gray;${dateDirection}">${dateString}</p>
<div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
</div>
`;
  } else {
    return `
<div id="msg-${event.getId()}" class="msgItem" sender="${sender}">
<div id="innermsg-${event.getId()}" class="msgInnerItem" style="${floatDirection}">
<pre>
${body}
</pre>
</div>
<p id="datetime-${event.getId()}" style="font-size:10px;color:gray;${dateDirection}">${dateString}</p>
<div id="reactions-${event.getId()}" class="reactions" style="${reactDirection}"></div>
</div>
`

  }

};

const gotoRoomView = () => {
  if(initSync) {
    highlightedRoom = 0;
  }
  const roomz = window.mClient.getRooms();
  const roomList = roomz.sort((roomA, roomB) => {
    return roomA.name.localeCompare(roomB.name);
  }).reduce((a, room) => {
    if (a === '<div>') {
      return a + `
<div id="room-${room.roomId}" class="roomItem active">
${room.name}
</div>
<br/>
`;
    } else {
      return a + `
<div id="room-${room.roomId}" class="roomItem">
${room.name}
</div>
<br/>
`;
    }
  }, '<div>'); + '</div>'
  document.getElementById('room-menu').style = 'display: unset';
  document.getElementById('chat').style = 'display: none';
  document.getElementById('chat-textbox').value = '';
  document.getElementById('chat-textbox').selectionStart = 0
  document.getElementById('chat-textbox').style.height = '24px';
  document.getElementById('conversation').style.height = '100%';
  document.getElementById('editing').style.bottom = '55px';
  document.getElementById('replying').style.bottom = '55px';
  document.getElementById('login').style = 'display: none';
  document.getElementById("left").innerHTML = "";
  document.getElementById("right").innerHTML = "";
  document.getElementById("middle").innerHTML = "SELECT";
	document.getElementById("title-text").innerHTML = 'Rooms';
  document.getElementById("room-menu").innerHTML = roomList;
  initSync = true;
  rooms = document.getElementsByClassName('roomItem');
  page = 'rooms';
  highlightedMsg = null;
};

const markReaction = (event, relation) => {
  const {
    event_id,
    rel_type,
    key
  } = relation;
  const msgItem = document.getElementById(`msg-${event_id}`);
  const reactionsEl = document.getElementById(`reactions-${event_id}`);
  if(msgItem && reactionsEl) {
    reactionsEl.innerHTML = reactionsEl.innerHTML + `
<div id="react-${event.getId()}" class="${relation.key} ${event.getSender()}" style="font-size:16px;">
${relation.key}
</div>
`
    // if the last message gets reacted, scroll down to see it
    const msgs = document.getElementsByClassName('msgItem');
    if(msgItem === msgs[msgs.length - 1]) {
      const conversationEl = document.getElementById("conversation");
      conversationEl.scrollTo(0, conversationEl.scrollHeight);
    }
  }
};

const removeReaction = (eventId) => {
  const reaction = document.getElementById(`react-${eventId}`);
  if(reaction)
    reaction.remove();
};

const replaceBody = (event, relation) => {
  const content = event.getContent();
  const innerMsgItem = document.getElementById(`innermsg-${relation.event_id}`);
  const newBody = content['m.new_content'].body;
  if(innerMsgItem)
    innerMsgItem.innerHTML = `
<pre>
${newBody + '<br/><b class="edited-marker" style="color:black">(edited)</b>'}
</pre>
`;
};

const prepareSession = (client) => {
  document.getElementById("room-menu").innerHTML = "Loading..."
	document.getElementById("title-text").innerHTML = 'Rooms';
  document.getElementById("left").innerHTML = "";
  document.getElementById("right").innerHTML = "";
  document.getElementById("middle").innerHTML = "SELECT";

  window.mClient = window.matrixcs.createClient({
    baseUrl: client.baseUrl,
    accessToken: client.access_token,
    userId: client.user_id,
    deviceId: client.device_id,
    sessionStore: new window.matrixcs.WebStorageSessionStore(localStorage),
  });
  window.mClient.on("sync", function(event) {
    if(!initSync) {
      gotoRoomView();
      // window.mClient.setDeviceVerified(window.mClient.getUserId(), window.mClient.getDeviceId()).then((d) => {
      //   console.log('DEVICE VERIFIED');
      // })
      // window.mClient.uploadKeys();
    }
  });
  window.mClient.on("Room.timeline", function(event, room, toStartOfTimeline) {
    const eventType = event.getType();
    const relation = event.getRelation();
    // console.log(event);
    if (page === 'chat' && currentRoom === room.roomId ) {
      switch(eventType) {
      case 'm.room.message': {
        if(!relation) {
          const newMsg = messageBuilder(event);
          const conversationEl = document.getElementById("conversation");
          const typing = document.getElementsByClassName('typing');
          let newTyping = '';
          for(var i = 0; i < typing.length; i++) {
            const div = typing[i];
            div.remove();
            newTyping = newTyping + div.outerHTML;
          }
          conversationEl.innerHTML = conversationEl.innerHTML + newMsg + newTyping;
          if(document.activeElement.id === 'chat-textbox') {
            conversationEl.scrollTo(0, conversationEl.scrollHeight);
          }
        } else {
          if(relation.rel_type === 'm.replace' && !event.isEncrypted)
            replaceBody(event, relation);
        }
        return;
      }
      case 'm.reaction': {
        if(relation && relation.rel_type === 'm.annotation') {
          markReaction(event, relation);
        }
        return;
      }
      case 'm.room.redaction': {
        removeReaction(event.event.redacts);
        return;
      }
      }
    }
  });
  window.mClient.on("RoomMember.typing", function(event, member) {
    const room = window.mClient.getRoom(currentRoom);
    if(room) {
      const members = room.getMembers().map(({userId}) => userId);
      if (page === 'chat' && members.indexOf(member.userId) > -1) {
        if (member.typing) {
          const typingDiv = `<div id="typing-${member.userId}" class="typing">${member.name} is typing...</div>`;
          const conv = document.getElementById('conversation');
          conv.innerHTML = conv.innerHTML + typingDiv;
          if(conv.clientHeight - conv.scrollTop < 20) {
            conv.scrollTo(0, conv.scrollHeight);
          }
        }
        else {
          const typingDiv = document.getElementById(`typing-${member.userId}`);
          if(typingDiv)
            typingDiv.remove();
        }
      }
    }
  });
  // window.mClient.on("Room.receipt", function(event, member) {
  //   const content = event.getContent();
  //   const reads = Object.keys(content);
  //   reads.forEach((eventId) => {
  //     if(page === 'chat') {
  //       const msg = document.getElementById(`msg-${eventId}`);
  //       if(member.userId !== msg.getAttribute('sender')) {
  //         const dateTime = document.getElementById(`datetime-${eventId}`);
  //         if(dateTime)
  //           dateTime.innerHTML = 'read <br/>' + dateTime.innerHTML;
  //       }
  //     }
  //   })
  // })
  // window.mClient.initCrypto().then(() => {
  window.mClient.startClient({
    initialSyncLimit: 10,
    lazyLoadMembers: true,
  });
  // });
};

const login = (baseUrl, user, password) => {
  const client = window.matrixcs.createClient(baseUrl);
  client.loginWithPassword(user, password).then((d) => {
    const session = {...d, baseUrl};
    localStorage.setItem(LOCAL_STORAGE_SESSION_KEY, JSON.stringify(session));
    prepareSession(session);
  }).catch((e) => {
    console.error(e);
    alert('Login error! Check all inputs.')
    document.getElementById('middle').innerHTML = 'LOGIN';
  });
};

const sendReaction = (emoji) => {
  const el = document.getElementsByClassName('msgItem msgItem-selected')[0];
  if(el) {
    if(el.innerHTML.indexOf(emoji) > -1) { // has one already
      const react = el.getElementsByClassName(`${emoji} ${window.mClient.getUserId()}`)[0];
      if (react) {
        const eventId = react.id.substring(6);
        return window.mClient.redactEvent(currentRoom, eventId).then(() => {
          console.log('redacted!');
        }).catch((e) => {
          console.log(e);
          alert('Failed to redact reaction to message: ', JSON.stringify(e));
        });
      }
    }
    const event_id = el.id.substring(4);
    const content = {
      'm.relates_to': {
        key: emoji,
        event_id,
        rel_type: 'm.annotation',
      }
    };
    const date = new Date();
    const tnxId = date.getTime()/1000;
    window.mClient.sendEvent(currentRoom, "m.reaction", content, tnxId).then(({event_id}) => {
      const room = window.mClient.getRoom(currentRoom);
      const newReact = document.getElementById(`react-~${room.roomId}:${tnxId}`);
      newReact.id = `react-${event_id}`;
    }).catch((e) => {
      console.log(e);
      alert(e.message);
    });
  }
};

const keydownListener = (e) => {
  if(page === 'login') {
    if(e.key === 'ArrowUp') {
      var inputs = document.getElementsByClassName('login-text');
      inputs[highlightedLoginInput].blur();
      highlightedLoginInput = highlightedLoginInput - 1;
      if(highlightedLoginInput === -1) {
        highlightedLoginInput = inputs.length - 1;
      }
      inputs[highlightedLoginInput].focus();
    } else if (e.key === 'ArrowDown') {
      var inputs = document.getElementsByClassName('login-text');
      inputs[highlightedLoginInput].blur();
      highlightedLoginInput = highlightedLoginInput + 1;
      if(highlightedLoginInput === inputs.length) {
        highlightedLoginInput = 0
      }
      inputs[highlightedLoginInput].focus();
    } else if (e.key === 'Enter' && document.getElementById('middle').innerHTML !== 'Loading...') {
      var baseUrl = document.getElementById('homeserver').value;
      var user = document.getElementById('user').value;
      var password = document.getElementById('password').value;
      document.getElementById('middle').innerHTML = 'Loading...'
      login(baseUrl, user, password);
    }
    return e;
  } else if (page === 'image') {
    if(e.key === 'Backspace') {
      setTimeout(() => {
        const conv = document.getElementById('conversation');
        conv.innerHTML = previousConv;
        previousConv = null;
        page = 'chat'
        const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
        if(msgItem) {
          msgItem.scrollIntoView({
            behavor: 'smooth',
            block: 'center',
            inline: 'nearest'
          });
        }
      }, 500);
    }
  } else {
    e.preventDefault();
    switch (e.key) {
    case "Enter": {
      if(page === 'rooms') {
        gotoChat();
        page = 'chat';
      } else if(page === 'chat') {
        const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
        if(msgItem) {
          const eventId = msgItem.id.substring(4);
          const image = document.getElementById(`image-${eventId}`)
          if(image) {
            const imageUrl = image.getAttribute('src');
            const conv = document.getElementById('conversation');
            previousConv = conv.innerHTML;
            conv.innerHTML = `<img src="${imageUrl}"/>`;
            page = 'image';
          }
        }
      }
      return;
    }
    case "ArrowUp": {
      if(page === 'rooms') {
        const cur = rooms[highlightedRoom];
        let num = highlightedRoom - 1
        if(num < 0) {
          num = rooms.length - 1;
        }
        const next = rooms[num];
        cur.className = "roomItem";
        next.className = "roomItem active";
        highlightedRoom = num;
      } else if(page === 'chat') {
        var msgs = document.getElementsByClassName('msgItem');
        if (highlightedMsg === 0) {
          document.getElementById('left').innerHTML = ''
          document.getElementById('middle').innerHTML = 'Loading...'
          document.getElementById('right').innerHTML = ''
          const room = window.mClient.getRoom(currentRoom);
          const timeline = room.getLiveTimeline();
          const originalLength = msgs.length;
          window.mClient.paginateEventTimeline(timeline, {backwards: true, limit: 10}).then((d) => {
            document.getElementById('left').innerHTML = 'Reply'
            document.getElementById('middle').innerHTML = 'SELECT';
            document.getElementById('right').innerHTML = 'Edit'
            const events = room.timeline;
            var relations = [];
            const eventList = events.reduce((a, event) => {
              const relation = event.getRelation();
              if(relation) {
                relations.push({event, relation});
                return a + '';
              }
              if (event.getType() === 'm.room.message') {
                return a + messageBuilder(event);
              }
              return a + '';
            }, '');
            document.getElementById("conversation").innerHTML = eventList;
            const newLength = document.getElementsByClassName('msgItem').length;
            highlightedMsg = newLength - originalLength;
            var newCurrent = document.getElementsByClassName('msgItem')[highlightedMsg];
            newCurrent.className = 'msgItem msgItem-selected';
            newCurrent.scrollIntoView({
              behavor: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            });
            // highlightedMsg = document.getElementsByClassName('msgItem').findIndex((e) => e = newCurrent);
            relations.forEach(({event, relation}) => {
              const {
                event_id,
                rel_type,
              } = relation;
              const msgItem = document.getElementById(`msg-${event_id}`);
              if(msgItem) {
                if(rel_type === 'm.annotation') {
                  markReaction(event, relation);
                } else if(rel_type === 'm.replace') {
                  replaceBody(event, relation);
                }
              }
              return;
            });

          });
          return;
        } else if(highlightedMsg !== msgs.length) {
          msgs[highlightedMsg].className = 'msgItem';
        }
        highlightedMsg = highlightedMsg - 1;
        msgs[highlightedMsg].className = 'msgItem msgItem-selected';
        msgs[highlightedMsg].scrollIntoView({
          behavor: 'smooth',
          block: 'nearest',
          inline: 'nearest'
        });
      }
      return;
    }
    case "ArrowDown": {
      if(page === 'rooms') {
        const cur = rooms[highlightedRoom];
        let num = highlightedRoom + 1
        if(num > rooms.length - 1) {
          num = 0;
        }
        const next = rooms[num];
        cur.className = "roomItem";
        next.className = "roomItem active";
        highlightedRoom = num;
      } else if (page === 'chat') {
        var msgs = document.getElementsByClassName('msgItem');
        var mNext = highlightedMsg + 1;
        if(mNext === msgs.length && !scrollMsg) {
          msgs[highlightedMsg].className = 'msgItem';
          highlightedMsg = msgs.length;
          document.getElementById('chat-textbox').focus();
        } else {
          if ((msgs[mNext] && msgs[mNext].clientHeight > document.getElementById('conversation').clientHeight) || scrollMsg) {
            if(!scrollMsg) {
              scrollMsg = msgs[mNext].clientHeight;
              document.getElementById('conversation').scrollBy({
                top: 100,
                left: 0,
                behavor: 'smooth',
              });
              scrollMsg = scrollMsg - 100;
            } else if(scrollMsg <= document.getElementById('conversation').clientHeight) {
              scrollMsg = null;
            }  else {
              document.getElementById('conversation').scrollBy({
                top: 100,
                left: 0,
                behavor: 'smooth',
              });
              scrollMsg = scrollMsg - 100;
              return;
            }
          }
          msgs[highlightedMsg].className = 'msgItem';
          if (mNext >= msgs.length) {
            document.getElementById('chat-textbox').focus();
          } else {
            highlightedMsg = mNext
            msgs[highlightedMsg].className = 'msgItem msgItem-selected';
            msgs[highlightedMsg].scrollIntoView({
              behavor: 'smooth',
              block: 'nearest',
              inline: 'nearest'
            });
          }
        }
      }
      return;
    }
    case "Shift":
    case "SoftRight": {
      if(page === 'chat') {
        const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
        if(msgItem) {
          const eventId = msgItem.id.substring(4);
          const innerMsg = document.getElementById(`innermsg-${eventId}`);
          if(innerMsg.style['align-self'] === 'flex-end') {
            let msg = innerMsg.innerText.trim();
            if(innerMsg.getElementsByClassName('edited-marker').length > 0) {
              msg = msg.slice(0, -9); // removed the "\n(edited)" part
            }
            document.getElementById('chat-textbox').value = msg;
            const editing = document.getElementById('editing');
            editing.style.display = 'unset';
            editingEvent = eventId;
            const chatBox = document.getElementById('chat-textbox');
            chatBox.focus();
            highlightedMsg += 1;
            if(chatBox.scrollHeight < 122) {
              chatBox.style.height = "auto";
              chatBox.style.height = (chatBox.scrollHeight) + "px";
              document.getElementById('editing').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
              document.getElementById('replying').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
            }
          }
        }
      }
      return;
    }
    case "Control":
    case "SoftLeft": {
      if(page === 'chat') {
        const msgItem = document.getElementsByClassName('msgItem msgItem-selected')[0];
        if(msgItem) {
          const eventId = msgItem.id.substring(4);
          const innerMsg = document.getElementById(`innermsg-${eventId}`);
          let msg = innerMsg.innerText.trim();
          if(innerMsg.getElementsByClassName('edited-marker').length > 0) {
            msg = msg.slice(0, -9); // removed the "\n(edited)" part
          }
          const replying = document.getElementById('replying');
          replying.style.display = 'unset';
          replyingToEvent = {
            eventId,
            sender: msgItem.getAttribute('sender'),
            body: msg,
          };
          const chatBox = document.getElementById('chat-textbox');
          chatBox.focus();
          highlightedMsg += 1;
          if(chatBox.scrollHeight < 122) {
            chatBox.style.height = "auto";
            chatBox.style.height = (chatBox.scrollHeight) + "px";
            document.getElementById('editing').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
            document.getElementById('replying').style.bottom = (chatBox.scrollHeight + 55 - 29) + "px";
          }
        }
      }
      return;
    }
    case "End":
    case "EndCall": {
      window.mClient.stopClient();
      close();
      return;
    }
    case "Backspace": {
      if(page === 'chat') {
        gotoRoomView();
      } else if (page === 'rooms') {
        // if(confirm("Close app?")) {
        window.mClient.stopClient();
        close();
        // }
      }
      return;
    }
    case "1": {
      sendReaction('👍');
      return;
    }
    case "2": {
      sendReaction('👎');
      return;
    }
    case "3": {
      sendReaction('❤️');
      return;
    }
    case "4": {
      sendReaction('🔥');
      return;
    }
    case "5": {
      sendReaction('🥰');
      return;
    }
    case "6": {
      sendReaction('🎉');
      return;
    }
    case "7": {
      sendReaction('😁');
      return;
    }
    case "8": {
      sendReaction('🤔');
      return;
    }
    case "9": {
      sendReaction('🤯');
      return;
    }
    case "0": {
      sendReaction('😱');
      return;
    }
    case "#": {
      sendReaction('😭');
      return;
    }
    case "*": {
      sendReaction('💩');
      return;
    }
    }
  }
};

document.addEventListener("DOMContentLoaded", async () => {
  const session = localStorage.getItem(LOCAL_STORAGE_SESSION_KEY);
  if(session) {
    const client = JSON.parse(session);
    prepareSession(client);
  } else {
	  document.getElementById("title-text").innerHTML = 'Login';
    document.getElementById("login").style = 'display: unset';
    document.getElementById("left").innerHTML = "";
    document.getElementById("right").innerHTML = "";
    document.getElementById("middle").innerHTML = "LOGIN";
    document.getElementById('homeserver').focus();
  }

  const chatBox = document.getElementById('chat-textbox');
  const chatDownKeydownListener = (e) => {
    const editing = document.getElementById('editing');
    const replying = document.getElementById('replying');
    if(e.key === 'ArrowUp' && chatBox.selectionStart === 0) {
      chatBox.blur();
      chatBox.removeEventListener('keydown', chatDownKeydownListener);
      var msgs = document.getElementsByClassName('msgItem');
      if(msgs[highlightedMsg])
        msgs[highlightedMsg].className = 'msgItem';
      highlightedMsg = msgs.length;
      // msgs[highlightedMsg].style = 'background-color: lightgray';
    } else if (e.key === 'Call' || e.key === 'F1') {
      var msgs = document.getElementsByClassName('msgItem');
      if(msgs[highlightedMsg]) {
        chatBox.blur();
        chatBox.removeEventListener('keydown', chatDownKeydownListener);
        highlightedMsg = highlightedMsg - 1;
        msgs[highlightedMsg].scrollIntoView({
          behavor: 'smooth',
          block: 'center',
          inline: 'nearest'
        });
      }
    } else if(e.key === 'Backspace' && chatBox.selectionStart === 0) {
      setTimeout(() => {
        chatBox.blur();
      }, 500);
      gotoRoomView(chatBox);
    } else if ((e.key === "SoftLeft" || e.key === "Control") && page === 'chat' && document.getElementById("left").innerHTML !== '') {
      if (editing.style.display === 'unset') { // editing
        const body = document.getElementById('chat-textbox').value.trim();
        const content = {
          body: ' * ' + body,
          msgtype: "m.text",
          'm.relates_to': {
            event_id: editingEvent,
            rel_type: 'm.replace',
          },
          'm.new_content': {
            body,
            msgtype: 'm.text',
          }
        };
        if (body !== '') {
          document.getElementById("left").innerHTML = "";
          document.getElementById("right").innerHTML = "";
          document.getElementById("middle").innerHTML = "SAVING...";
          document.getElementById("chat-textbox").disabled = true;
          const date = new Date();
          const tnxId = date.getTime()/1000;
          window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
            document.getElementById('chat-textbox').value = '';
            document.getElementById("chat-textbox").disabled = false;
            document.getElementById("chat-textbox").style.height = "24px";
            document.getElementById('chat-textbox').selectionStart = 0
            document.getElementById('conversation').style.height = '100%';
            document.getElementById('editing').style.bottom = "55px";
            editing.style.display = 'none';
            editingEvent = null;
            // const msg = document.getElementsByClassName('msgItem msgItem-selected')[0];
            // msg.className = 'msgItem';
            // highlightedMsg = null;

            // const room = window.mClient.getRoom(currentRoom);
            // const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
            // const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
            // newMsg.id = `msg-${event_id}`;
            // newInnerMsg.id = `innermsg-${event_id}`;
            return;
          }).catch((err) => {
            alert('Failed to send message: ', JSON.stringify(err));
            console.log(err);
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
          });
        }
      } else if (replying.style.display === 'unset') { // replying
        const body = document.getElementById('chat-textbox').value.trim();
        const content = {
          body: `> <${replyingToEvent.sender}> ${replyingToEvent.body}` + '\n\n' + body,
          format: 'org.matrix.custom.html',
          formatted_body: `<mx-reply><blockquote><a href=\"https://matrix.to/#/${currentRoom}/${replyingToEvent.eventId}">In reply to</a> <a href="https://matrix.to/#/${replyingToEvent.sender}">${replyingToEvent.sender}</a><br>${replyingToEvent.body}</blockquote></mx-reply>${body}`,
          msgtype: "m.text",
          'm.relates_to': {
            'm.in_reply_to': {
              event_id: replyingToEvent.eventId,
            },
          },
        };
        if (body !== '') {
          document.getElementById("left").innerHTML = "";
          document.getElementById("right").innerHTML = "";
          document.getElementById("middle").innerHTML = "SENDING...";
          document.getElementById("chat-textbox").disabled = true;
          const date = new Date();
          const tnxId = date.getTime()/1000;
          window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
            document.getElementById('chat-textbox').value = '';
            document.getElementById("chat-textbox").disabled = false;
            document.getElementById("chat-textbox").style.height = "24px";
            document.getElementById('chat-textbox').selectionStart = 0
            document.getElementById('conversation').style.height = '100%';
            document.getElementById('editing').style.bottom = "55px";
            replying.style.display = 'none';
            replyingToEvent = null;
            // const msg = document.getElementsByClassName('msgItem msgItem-selected')[0];
            // msg.className = 'msgItem';
            // highlightedMsg = null;

            const room = window.mClient.getRoom(currentRoom);
            const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
            const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
            newMsg.id = `msg-${event_id}`;
            newInnerMsg.id = `innermsg-${event_id}`;
            return;
          }).catch((err) => {
            alert('Failed to send message: ', JSON.stringify(err));
            console.log(err);
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
          });
        }
      } else {
        const body = document.getElementById('chat-textbox').value.trim();
        const content = {
          body,
          msgtype: "m.text"
        };
        if (body !== '') {
          document.getElementById("left").innerHTML = "";
          document.getElementById("right").innerHTML = "";
          document.getElementById("middle").innerHTML = "SENDING...";
          document.getElementById("chat-textbox").disabled = true;
          const date = new Date();
          const tnxId = date.getTime()/1000;
          window.mClient.sendEvent(currentRoom, "m.room.message", content, tnxId).then(({event_id}) => {
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
            document.getElementById('chat-textbox').value = '';
            document.getElementById("chat-textbox").disabled = false;
            document.getElementById("chat-textbox").style.height = "24px";
            document.getElementById('chat-textbox').selectionStart = 0
            document.getElementById('conversation').style.height = '100%';
            document.getElementById('replying').style.bottom = "55px";
            const room = window.mClient.getRoom(currentRoom);
            const newMsg = document.getElementById(`msg-~${room.roomId}:${tnxId}`);
            const newInnerMsg = document.getElementById(`innermsg-~${room.roomId}:${tnxId}`);
            newMsg.id = `msg-${event_id}`;
            newInnerMsg.id = `innermsg-${event_id}`;
            return;
          }).catch((err) => {
            alert('Failed to send message: ', JSON.stringify(err));
            console.log(err);
            document.getElementById("left").innerHTML = "Send";
            document.getElementById("right").innerHTML = "";
            document.getElementById("middle").innerHTML = "ENTER";
          });
        }
      }
    } else if ((e.key === "SoftRight" || e.key === "Shift") && page === 'chat' && document.getElementById("right").innerHTML !== '') { // cancel edit
      editing.style.display = 'none';
      replying.style.display = 'none';
      document.getElementById('chat-textbox').value = '';
      document.getElementById('chat-textbox').selectionStart = 0
      document.getElementById("chat-textbox").style.height = "24px";
      document.getElementById('editing').style.bottom = "55px";
      document.getElementById('replying').style.bottom = "55px";
      document.getElementById("left").innerHTML = "Send";
      document.getElementById("right").innerHTML = "";
      document.getElementById("middle").innerHTML = "ENTER";
      editingEvent = null;
      replyingToEvent = null;
      const msg = document.getElementsByClassName('msgItem msgItem-selected')[0];
      msg.className = 'msgItem';
      highlightedMsg = null;
    }
  };
  chatBox.addEventListener("focus", (e) => {
    const editing = document.getElementById('editing');
    const replying = document.getElementById('replying');
    if(editing.style.display === 'unset') { // is editting
      document.getElementById("left").innerHTML = "Save";
      document.getElementById("right").innerHTML = "Discard";
      document.getElementById("middle").innerHTML = "ENTER";
    } else if (replying.style.display === 'unset') {
      document.getElementById("left").innerHTML = "Send";
      document.getElementById("right").innerHTML = "Discard";
      document.getElementById("middle").innerHTML = "ENTER";
    } else {                    // new msg
      document.getElementById("left").innerHTML = "Send";
      document.getElementById("right").innerHTML = "";
      document.getElementById("middle").innerHTML = "ENTER";
      const scrollHeight = document.getElementById("conversation").scrollHeight;
      document.getElementById("conversation").scrollTo(0, scrollHeight);
    }
    document.removeEventListener('keydown', keydownListener);
    chatBox.addEventListener('keydown', chatDownKeydownListener)
  });

  chatBox.addEventListener("blur", (e) => {
    if(page === 'chat') {
      document.getElementById("left").innerHTML = "Reply";
      document.getElementById("right").innerHTML = "Edit";
      document.getElementById("middle").innerHTML = "SELECT";
    }
    document.addEventListener('keydown', keydownListener);
  });

  // auto resize the text boxes
  const tx = document.getElementsByTagName("textarea");
  for (let i = 0; i < tx.length; i++) {
    tx[i].setAttribute("style", "height:24px;overflow-y:hidden;");
    tx[i].addEventListener("input", OnInput, false);
  };

  function OnInput() {
    if(this.scrollHeight < 122) {
      this.style.height = "auto";
      this.style.height = (this.scrollHeight) + "px";
      const conv = document.getElementById("conversation");
      conv.style.height = `calc(100% - ${this.scrollHeight + 52}px)`;
      if(document.getElementById('editing').style.display === 'none'
         &&
         document.getElementById('replying').style.display === 'none') {
        conv.scrollTo(0, conv.scrollHeight);
      }
      document.getElementById('editing').style.bottom = (this.scrollHeight + 55 - 29) + "px";
      document.getElementById('replying').style.bottom = (this.scrollHeight + 55 - 29) + "px";
    }
  };


});

const gotoChat = () => {
  const roomEl = document.getElementsByClassName('roomItem active')[0];
  const id = roomEl.id.substring(5);
  const room = window.mClient.getRoom(id);
  // const timeline = room.getLiveTimeline();
  // const rest = window.mClient.paginateEventTimeline(timeline, {backwards: true}).then((d) => {
  const events = window.mClient.getRoom(id).timeline;
  var relations = [];
  const eventList = events.reduce((a, event) => {
    const relation = event.getRelation();
    if(relation) {
      relations.push({event, relation});
      return a + '';
    }
    if (event.getType() === 'm.room.message') {
      // window.mClient.decryptEventIfNeeded(event, {isRetry: false, emit: true}).then((d) => {
        // const events = window.mClient.getRoom(id).timeline;
      //   console.log('DECRYPTED: ', d);
      // })
      return a + messageBuilder(event);
    }
    return a + '';
  }, '');
  document.getElementById("conversation").innerHTML = eventList;
  relations.forEach(({event, relation}) => {
    const {
      event_id,
      rel_type,
    } = relation;
    const msgItem = document.getElementById(`msg-${event_id}`);
    if(msgItem) {
      if(rel_type === 'm.annotation') {
        markReaction(event, relation);
      } else if(rel_type === 'm.replace') {
        replaceBody(event, relation);
      }
    }
    return;
  });
  document.getElementById('room-menu').style = 'display: none';
  document.getElementById('chat').style = 'display: flex';
  document.getElementById('chat-textbox').value = '';
  document.getElementById('chat-textbox').focus();
	document.getElementById("title-text").innerHTML = room.name;
  document.getElementById("left").innerHTML = "Send";
  document.getElementById("right").innerHTML = "";
  document.getElementById("middle").innerHTML = "ENTER";
  setTimeout(() => {
    const scrollHeight = document.getElementById("conversation").scrollHeight;
    document.getElementById("conversation").scrollTo(0, scrollHeight);
  }, 500);
  currentRoom = id;
};

document.addEventListener("keydown", keydownListener);
